﻿using Colorful.Furniture.Extensions;
using Colorful.Furniture.MpManagement;
using Colorful.Furniture.PermissionManagement;
using Colorful.Furniture.Wrappers;
using FreeSql;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Services;
using Volo.Abp.Guids;
using Volo.Abp.Security.Claims;

namespace Colorful.Furniture.UserManagement;

/// <summary>
///  用户服务
/// </summary>
[Authorize]
public class UserAppService : ApplicationService
{
    private readonly WechatMpUserAppService _mpUserAppService;
    private readonly IBaseRepository<User> _userRepository;
    private readonly IGuidGenerator _guidGenerator;
    private readonly ColorfulJwtOptions _colorfulJwtOptions;
    private readonly IBaseRepository<UserIdentity> _userIdentityRepository;
    private readonly IFreeSql _freeSql;

    public UserAppService(
        WechatMpUserAppService mpUserAppService,
        IBaseRepository<User> userRepository,
        IGuidGenerator guidGenerator,
        IFreeSql freeSql,
        IOptions<ColorfulJwtOptions> colorfulJwtOptions, 
        IBaseRepository<UserIdentity> userIdentityRepository)
    {
        _mpUserAppService = mpUserAppService;
        _userRepository = userRepository;
        _guidGenerator = guidGenerator;
        _freeSql = freeSql;
        _userIdentityRepository = userIdentityRepository;
        _colorfulJwtOptions = colorfulJwtOptions.Value;
    }

    /// <summary>
    ///  同步公众号关注用户数据
    /// </summary>
    /// <returns></returns>
    public async Task<bool> SyncUserByMpAsync()
    {
        //获取所有订阅的用户
        var allSubscribeUser = await _mpUserAppService.GetAllListAsync();

        using var unitOfWork = _freeSql.CreateUnitOfWork();
        _userRepository.UnitOfWork = unitOfWork;

        var userList = allSubscribeUser.Select(x =>
        {
            var user = new User
            {
                Id = _guidGenerator.Create(),
                AddTime = (x.SubscribeTimestamp * 1000).ToLong().ToDateTime(),
                Amount = 0,
                AvatarUrl = "http://jiaju-api.zgxhcs.net/images/default_avatar.png",
                Remark = x.Remark,
                Name = $"新红鹰用户-{CommonUtils.Number(4)}",
                NickName = $"XHY-{CommonUtils.Number(8)}",
                Point = 0,
                Sex = "未知",
                Status = 1,
            };

            user.UserIdentities = new List<UserIdentity>
            {
                new()
                {
                    IdentityType = IdentityType.微信公众号,
                    Identifier = user.NickName,
                    AddTime = Clock.Now,
                    Credential = x.OpenId
                }
            };

            return user;
        });

        foreach (var user in userList)
        {
            await _userRepository.InsertAsync(user);
            await _userRepository.SaveManyAsync(user, nameof(User.UserIdentities));
        }

        unitOfWork.Commit();

        return true;
    }
    

    /// <summary>
    ///  生成用户token
    /// </summary>
    /// <param name="userId">用户标识</param>
    /// <returns></returns>
    [RemoteService(IsEnabled = false)]
    public string GenerateUserToken(Guid? userId)
    {
        if (!userId.HasValue)
            throw new UserFriendlyException($"生成用户凭证失败，{nameof(userId)}为空");

        //写入相应的claim信息到请求安全体中
        var userClaims = new List<Claim>
        {
            new(AbpClaimTypes.UserId, userId.ToString()),
            new(AbpClaimTypes.Role, FurnitureConsts.AuthorizeUserRole)
        };

        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_colorfulJwtOptions.SecurityKey));
        //jwt证书
        var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
        var securityToken = new JwtSecurityToken(
            _colorfulJwtOptions.Issuer,
            _colorfulJwtOptions.Audience,
            userClaims,
            DateTime.Now,
            DateTime.Now.AddYears(2),
            credentials);

        var token = new JwtSecurityTokenHandler().WriteToken(securityToken);

        return token;
    }
}